﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Admin.Core.Service.sys.Org/SysOrgServiceImpl 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       SysOrgServiceImpl
* 创建时间：  2025/6/4 15:58:41
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using DotNetCore.CAP.Dashboard;
using Mapster;
using MapsterMapper;
using Microsoft.EntityFrameworkCore;
using SSPivot.Admin.Core.DbModel.sys;
using SSPivot.Admin.Core.Repository;
using SSPivot.Admin.Core.Service.sys.Org.Dto;
using SSPivot.AspNetCore.Abstractions.User;
using SSPivot.AspNetCore.Services;
using SSPivot.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace SSPivot.Admin.Core.Service.sys.Org
{
    /// <summary>
    /// 部门服务
    /// </summary>
    public class SysOrgServiceImpl : ApplicationService, ISysOrgService
    {
        #region 接口注入
        public ISSPivotRepository<sys_org> SysOrgRepository { get; set; }
        public ISSPivotRepository<sys_user_org> SysUserOrgRepository { get; set; }
        public ISSPivotRepository<sys_role_org> SysRoleOrgRepository { get; set; }
        public ICurrentUser CurrentUser { get; set; }
        #endregion

        #region 服务

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<SysOrgDto> GetAsync(long id)
        {
            var data = await SysOrgRepository.GetAsync(id);
            return data.Adapt<SysOrgDto>();
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<List<SysOrgListDto>> GetListAsync(string key)
        {
            var dataPermission = CurrentUser.DataPermission;
            var query = SysOrgRepository.Query();
            if (dataPermission.OrgIds.Count() > 0)
                query = query.Where(e => dataPermission.OrgIds.Contains(e.Id));
            if (dataPermission.DataScope == DataScope.Self)
                query = query.Where(e => e.CreatorId == CurrentUser.Id);
            if (key.IsNotNullOrWhiteSpace())
                query = query.Where(e => e.Name.Contains(key) || e.Code.Contains(key));
            var data = await query.ToListAsync();

            data = data?.Count > 0 ? data.DistinctBy(a => a.Id).OrderBy(a => a.ParentId).ThenBy(a => a.Sort).ToList() : data;
            return data.Adapt<List<SysOrgListDto>>();
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<long> AddAsync(SysOrgDto model)
        {
            if (model.ParentId == 0)
            {
                throw ServiceResult.Exception("请选择上级部门");
            }

            if (await SysOrgRepository.QueryNoTracking(a => a.ParentId == model.ParentId && a.Name == model.Name).AnyAsync())
            {
                throw ServiceResult.Exception("此部门已存在");
            }

            if (model.Code.IsNotNullOrEmpty() && await SysOrgRepository.QueryNoTracking(a => a.ParentId == model.ParentId && a.Code == model.Code).AnyAsync())
            {
                throw ServiceResult.Exception("此部门编码已存在");
            }

            var entity = Mapper.Map<sys_org>(model);

            if (entity.Sort == 0)
            {
                var sort = await SysOrgRepository.QueryNoTracking(a => a.ParentId == model.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await this.SetParentsValue(entity);
            await SysOrgRepository.AddAsync(entity);
            //删除缓存
            await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.DataPermission + "*");

            return entity.Id;
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateAsync(SysOrgDto input)
        {
            if (input.ParentId == 0)
            {
                throw ServiceResult.Exception("请选择上级部门");
            }

            var entity = await SysOrgRepository.GetAsync(input.Id);
            if (!(entity?.Id > 0))
            {
                throw ServiceResult.Exception("部门不存在");
            }

            if (input.Id == input.ParentId)
            {
                throw ServiceResult.Exception("上级部门不能是本部门");
            }

            if (await SysOrgRepository.QueryNoTracking(a => a.ParentId == input.ParentId && a.Id != input.Id && a.Name == input.Name).AnyAsync())
            {
                throw ServiceResult.Exception("此部门已存在");
            }

            if (input.Code.IsNotNullOrEmpty() && await SysOrgRepository.QueryNoTracking(a => a.ParentId == input.ParentId && a.Id != input.Id && a.Code == input.Code).AnyAsync())
            {
                throw ServiceResult.Exception("此部门编码已存在");
            }

            var childIdList = await this.GetChildrenIdListAsync(input.Id.Value);
            if (childIdList.Contains(input.ParentId))
            {
                throw ServiceResult.Exception("上级部门不能是下级部门");
            }

            Mapper.Map(input, entity);
            await this.SetParentsValue(entity);
            await SysOrgRepository.UpdateAsync(entity);
            //删除缓存
            await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.DataPermission + "*");
        }

        /// <summary>
        /// 彻底删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>    
        public async Task DeleteAsync(long id)
        {
            //本部门下是否有员工
            if (await SysUserOrgRepository.QueryNoTracking(e => e.OrgId == id).AnyAsync())
            {
                throw ServiceResult.Exception("当前部门有员工无法删除");
            }

            var orgIdList = await this.GetChildrenIdListAsync(id);
            //本部门的下级部门下是否有员工
            if (await SysUserOrgRepository.QueryNoTracking(e => orgIdList.Contains(e.Id)).AnyAsync())
            {
                throw ServiceResult.Exception("本部门的下级部门有员工无法删除");
            }

            //删除部门角色
            await SysRoleOrgRepository.QueryIgnoreQueryFilters(a => orgIdList.Contains(a.OrgId)).ExecuteDeleteAsync();

            //删除本部门和下级部门
            await SysOrgRepository.QueryIgnoreQueryFilters(a => orgIdList.Contains(a.Id)).ExecuteDeleteAsync();
            //删除缓存
            await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.DataPermission + "*");
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>    
        public async Task SoftDeleteAsync(long id)
        {
            //本部门下是否有员工
            if (await SysUserOrgRepository.QueryNoTracking(e => e.OrgId == id).AnyAsync())
            {
                throw ServiceResult.Exception("当前部门有员工无法删除");
            }

            var orgIdList = await this.GetChildrenIdListAsync(id);
            //本部门的下级部门下是否有员工
            if (await SysUserOrgRepository.QueryNoTracking(e => orgIdList.Contains(e.Id)).AnyAsync())
            {
                throw ServiceResult.Exception("本部门的下级部门有员工无法删除");
            }

            //删除部门角色
            await SysRoleOrgRepository.Query(a => orgIdList.Contains(a.OrgId)).ExecuteDeleteAsync();

            //删除本部门和下级部门
            await SysOrgRepository.Query(a => orgIdList.Contains(a.Id)).ExecuteDeleteAsync();
            //删除缓存
            await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.DataPermission + "*");
        }

        #endregion

        #region tree

        /// <summary>
        /// 获得本级和下级Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<long>> GetChildrenIdListAsync(long id)
        { 
            return await SysOrgRepository.QueryNoTracking(e => e.ParentIds.Contains(id.ToString())).Select(e => e.Id).ToListAsync(); 
        }

        /// <summary>
        /// 获取上级
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<SysOrgDto>> GetSupCategory(long id)
        {
            var result = new List<SysOrgDto>();
            var current = await this.GetAsync(id);
            if (current != null)
            {
                if (current.ParentId != 0)
                {
                    result.AddRange(await this.GetSupCategory(current.Id.Value));
                }
                result.Add(current);
            }
            return result;
        }

        /// <summary>
        /// 获取上级名称
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<string>> GetSupCategoryName(long id)
        {
            var data = await this.GetSupCategory(id);
            return data.Select(e => e.Name).ToList();
        }

        /// <summary>
        /// 获取下级部门带层级
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<List<SysOrgDto>> GetSubCategoryTreeAsync(QuerySysOrgRequest model)
        {
            var result = new List<SysOrgDto>();
            var query = SysOrgRepository.QueryNoTracking();
            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    query = query.Where(e => e.Id == model.ParentId);
                else
                    query = query.Where(e => e.ParentId == model.ParentId);
            }
            else
            {
                query = query.Where(e => e.ParentId == 0);
            }
            var data = await query.ToListAsync();
            var listData = data.Adapt<List<SysOrgDto>>();
            var allEntity = await SysOrgRepository.QueryNoTracking(e => true, e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysOrgDto>>();
            foreach (var item in listData)
            {
                result.Add(RecursionCategory(item, allData));
            }
            return result;
        }

        /// <summary>
        /// 获取类别tree
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysOrgDto>> GetAllDataTreeAsync(QuerySysOrgRequest model)
        {
            var allEntity = await SysOrgRepository.QueryNoTracking(this.BuildSearch(model), e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysOrgDto>>();
            var mainData = allData.Where(e => e.ParentId == 0).ToList();
            var result = new List<SysOrgDto>();
            foreach (var item in allData)
            {
                result.Add(RecursionCategory(item, allData));
            }

            return result;
        }
        /// <summary>
        /// 递归获取所有子级部门及层级
        /// </summary>
        /// <param name="model"></param>
        public SysOrgDto RecursionCategory(SysOrgDto model, List<SysOrgDto> allData)
        {
            var childData = allData.Where(e => e.ParentId == model.Id).ToList();
            if (childData != null && childData.Count() > 0)
            {
                if (model.Children == null || model.Children.Count() == 0)
                    model.Children = new List<SysOrgDto>();
                foreach (var child in childData)
                {
                    child.Level = model.Level + 1;
                    model.Children.Add(RecursionCategory(child, allData));
                }

            }
            return model;
        }
        #endregion
        #region private
        private Expression<Func<sys_org, bool>> BuildSearch(QuerySysOrgRequest model)
        {
            Expression<Func<sys_org, bool>> whereCondition = e => true;
            if (model.Key.IsNotNullOrWhiteSpace())
                whereCondition = whereCondition.And(e => e.Name.Contains(model.Key));

            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    whereCondition = whereCondition.And(e => e.Id == model.ParentId);
                else
                    whereCondition = whereCondition.And(e => e.ParentId == model.ParentId);
            }
            else
            {
                whereCondition = whereCondition.And(e => e.ParentId == 0);
            }
            if (model.SDate.HasValue)
                whereCondition = whereCondition.And(e => e.CreatedTime > model.SDate);

            if (model.EDate.HasValue)
            {
                var date = model.EDate.Value.AddDays(1);
                whereCondition = whereCondition.And(e => e.CreatedTime < date);
            }
            return whereCondition;
        }

        private Dictionary<Expression<Func<sys_org, dynamic>>, SortType> BuildSort(QuerySysOrgRequest model)
        {
            var orderBy = new Dictionary<Expression<Func<sys_org, dynamic>>, SortType>();

            orderBy.Add(e => e.Id, SortType.Desc);
            return orderBy;
        }
        private async Task<sys_org> SetParentsValue(sys_org model)
        {
            if (model.ParentId == 0)
            {
                var pids = new List<long>() { model.Id };
                var names = new List<string>() { model.Name };
                model.ParentId = 0;
                model.ParentIds = pids.SerializeJson();
                model.ParentNames = names.SerializeJson();

            }
            else
            {
                var parent = (await SysOrgRepository.QueryNoTracking(x => x.Id == model.ParentId).FirstOrDefaultAsync()).Adapt<SysOrgDto>();
                parent.ParentIds.Add(model.Id);
                model.ParentIds = parent.ParentIds.SerializeJson();
                parent.ParentNames.Add(model.Name);
                model.ParentNames = parent.ParentNames.SerializeJson();
            }
            return model;
        }
        #endregion
    }
}